package cn.maydaymemory.mastery.message.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NeatText implements Cloneable{
    private List<String> texts;
    private List<Boolean> frontAlignment;
    private int width;

    public NeatText(){
        texts=new ArrayList<>();
        frontAlignment=new ArrayList<>();
        width=32;
    }

    public NeatText clone(){
        try {
            return (NeatText) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param text 需要添加的一个段落
     * @param front true-向前对齐 false-向后对齐
     * @return 返回当前NeatText的实例。
     */
    public NeatText addText(String text,boolean front){
        texts.add(toDBC(text));
        frontAlignment.add(front);
        return this;
    }

    /**
     * @param index 需要删除的段落的下标
     * @return 返回当前NeatText的实例。
     */
    public NeatText removeTest(int index){
        texts.remove(index);
        frontAlignment.remove(index);
        return this;
    }

    /**
     * @return 返回当前NeatText设置的宽度
     * 如果一个段落的长度超过NeatText的宽度，将会自动换行。
     */
    public int width(){
        return width;
    }

    /**
     * @param width 设置当前NeatText的宽度
     * @return 返回当前NeatText的实例。
     * 如果一个段落的长度超过NeatText的宽度，将会自动换行。
     */
    public NeatText width(int width){
        if(width>0){
            this.width=width;
        }else this.width=32;
        return this;
    }


    /**
     * 内部方法，用于分割段落，自动换行。
     * @param string 需要分割的段落
     * @param frontAlignment 是否向前对齐
     * @param width 分割成长度为width的若干小段
     * @return 分割完的段落
     */
    private String getStringByEnter(int width, String string ,boolean frontAlignment)
    {
        int color = 0;
        int zh = 0;
        for (int i = 0; i < string.length(); i++)
        {
            if(string.charAt(i)=='§')color++;
            if(isChineseChar(string.charAt(i)))zh++;
            try {
                if (string.substring(0, i+1).getBytes("GB18030").length+zh*0.250-color*3 > width)
                {
                    return string.substring(0, i) + "\n" +
                            getStringByEnter(width, string.substring(i),frontAlignment);
                }
            } catch (UnsupportedEncodingException ignore) {}
        }
        return (frontAlignment ? string : fixedLengthString(string,width) );
    }

    /**
     * @param prefix 每个段落需要带有的前缀
     * @return 返回每个段落带有前缀的整齐的文本。
     */
    public List<String> getTexts(String prefix){
        List<String> result = new ArrayList<>();
        int iter = 0;
        for(String text:texts){
            result.add(getStringByEnter(width(),prefix+text,frontAlignment.get(iter)));
            iter++;
        }
        return result;
    }

    /**
     * @return 返回没有段落前缀的整齐的文本。
     */
    public List<String> getTexts(){
        List<String> result = new ArrayList<>();
        for(int f = 0;f<texts.size();f++)  result.add(getStringByEnter(width,texts.get(f),frontAlignment.get(f)));
        return result;
    }

    /**
     * 内部方法，用于设置向后对齐还是向前对齐
     * @param string 需要对齐的字符串
     * @param width 宽度
     * @return 对齐后的文本。（如果向后对齐，将用空格填充）
     */
    private static String fixedLengthString(String string, int width) {
        return String.format("%1$"+(width-(getTLength(string)-string.length()))+ "s", string);
    }

    private static int getTLength(String string){
        int gbklength = StringUtil.getGBKLengthWithoutColorCode(string);
        String regex = "[\\u4e00-\\u9fa5]";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(string);
        int count=0;
        while (matcher.find()) {
            count++;
        }
        return (int)(gbklength+count*0.250);
    }

    private static String toDBC(String input) {
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == '\u3000') {
                c[i] = ' ';
            } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
                c[i] = (char) (c[i] - 65248);

            }
        }
        return new String(c);
    }

    private static boolean isChineseChar(char c) {
        return String.valueOf(c).matches("[\u4e00-\u9fa5]");
    }
}
